﻿using System;
using Microsoft.DirectX.Direct3D;
using cz.zcu.PreSti.DirectX;
using System.IO;
using cz.zcu.PreSti.XNADirectX;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Drawing;

namespace cz.zcu.PreSti.Components
{
    public class ImageStimulus : RunnableComponent
    {
        private XNADirectXPresentation xnaPresentation = null;
        private String path = "";
        private System.Drawing.Point position = System.Drawing.Point.Empty;
        private SizeF size = SizeF.Empty;
        private PointF rotationCenter = PointF.Empty;
        private float rotation = 0;
        private Texture2D texture = null;
        private bool pathChanged = true;

        public ImageStimulus(IPresentation p) : base(p, 2, 1, 9, 0)
        {
            xnaPresentation = (XNADirectXPresentation)p;
            Finished += new EventHandler(onFinished);
        }

        #region parameters

        public String Path
        {
            get
            {
                return path;
            }
            set
            {
                path = value;
                pathChanged = true;
            }
        }

        public System.Drawing.Point Position
        {
            get
            {
                return position;
            }
            set
            {
                position = value;
            }
        }

        public SizeF Size
        {
            get
            {
                return size;
            }
            set
            {
                size = value;
            }
        }

        public PointF RotationCenter
        {
            get
            {
                return rotationCenter;
            }
            set
            {
                rotationCenter = value;
            }
        }

        public float Rotation
        {
            get
            {
                return rotation;
            }
            set
            {
                rotation = value;
            }
        }

        #endregion
        
        public override void update()
        {  
            if (pathChanged && texture != null)
            {
                loadTexture();
                pathChanged = false;
            }
        }

        public override void draw()
        {
            if (texture == null)
            {
                loadTexture();
            }

            if (xnaPresentation != null)
            {
                Microsoft.Xna.Framework.Rectangle screenRectangle = createImageRectangle();                
                Vector2 rotationCenterVector = new Vector2(rotationCenter.X, rotationCenter.Y);

                // delay analysis 
                xnaPresentation.startStopClock();

                xnaPresentation.SpriteBatch.Draw(texture, 
                    screenRectangle,
                    screenRectangle, 
                    Microsoft.Xna.Framework.Color.White, 
                    rotation,
                    rotationCenterVector, 
                    SpriteEffects.None, 
                    0f);
            }
        }

        private Microsoft.Xna.Framework.Rectangle createImageRectangle()
        {
            int defaultPicSize = 500;

            int width = 0;
            int height = 0;

            // handling no input width or height
            if ((int)size.Width == 0)
            {
                width = defaultPicSize;
            }
            else
            {
                width = (int)size.Width;
            }

            if ((int)size.Height == 0)
            {
                height = defaultPicSize;
            }
            else
            {
                height = (int)size.Height;
            }

            Microsoft.Xna.Framework.Rectangle rectangle
                = new Microsoft.Xna.Framework.Rectangle(position.X, position.Y, width, height);

            return rectangle;
        }

        public void loadTexture()
        {
            try
            {
                if ((path != null) && 
                    (File.Exists(System.IO.Path.GetFullPath(path))))
                {
                    using (Stream stream = File.OpenRead(System.IO.Path.GetFullPath(path)))
                    {
                        texture = Texture2D.FromStream(xnaPresentation.GraphicsDevice, stream);
                    }
                }
                else
                {
                    throw new Direct3DXException();
                }
            }
            catch (Direct3DXException)
            {
                presentation.LastError = "Cannot load image for ImageStimulus. Tha path to the file is probably incorrect.";
                Console.Out.WriteLine(presentation.LastError);
                presentation.terminate();
            }
        }

        private void onFinished(object sender, EventArgs e)
        {
            trigOut(0);
        }

        public override void trigIn(int n)
        {
            switch (n)
            {
                case 0:
                    base.trigIn(n);
                    break;
                case 1:
                    terminate();
                    break;
            }
        }

        public override void setValueToSetter(int setterN, object value)
        {
            base.setValueToSetter(setterN, value);
            int tmp;
            float tmpF;
            string tmpS;
            switch (setterN)
            {
                case 1:
                    tmpS = Path;
                    convertValue(ref tmpS, value);
                    Path = tmpS;
                    break;
                case 2:
                    tmp = position.X;
                    convertValue(ref tmp, value);
                    position.X = tmp;
                    break;
                case 3:
                    tmp = position.Y;
                    convertValue(ref tmp, value);
                    position.Y = tmp;
                    break;
                case 4:
                    tmpF = size.Width;
                    convertValue(ref tmpF, value);
                    size.Width = tmpF;
                    break;
                case 5:
                    tmpF = size.Height;
                    convertValue(ref tmpF, value);
                    size.Height = tmpF;
                    break;
                case 6:
                    tmpF = rotationCenter.X;
                    convertValue(ref tmpF, value);
                    rotationCenter.X = tmpF;
                    break;
                case 7:
                    tmpF = rotationCenter.Y;
                    convertValue(ref tmpF, value);
                    rotationCenter.Y = tmpF;
                    break;
                case 8:
                    convertValue(ref rotation, value); break;
            }
        }
    }
}